<?php
/**
 * @author winky
 */
namespace Think;

class Captcha
{

    private $width; // 宽度
    private $height; // 高度
    private $codeNum; // 验证码字符数量
    private $image; // 验证码图像资源
    private $captcha; // 验证码字符串
    const charWidth = 10; // 单个字符宽度,根据输出字符大小而变
    
    /**
     * 创建验证码类，初始化相关参数
     * 
     * @param int $width 图片宽度
     * @param int $height 图片高度
     * @param int $codeNum 验证码字符数量
     */
    function __construct($width = 50, $height = 20, $codeNum = 4)
    {
        $this->width = $width;
        $this->height = $height;
        $this->codeNum = $codeNum;
        
        // 保证最小高度和宽度
        if ($height < 20) {
            $this->height = 20;
        }
        if ($width < ($codeNum * self::charWidth + 10)) {
            $this->width = $codeNum * self::charWidth + 10;
        }
    }

    /**
     * 输出验证码图片
     * 
     * @return image
     */
    public function buildAndExportImage()
    {
        $this->exportImage();
    }
    
    /**
     * 构造并输出验证码
     *         
     * @return string
     */
    public function getCaptcha()
    {
        $this->createImage();
        $this->setDisturb();
        $this->setCaptcha();
        return $this->captcha;
    }

    /**
     * 构造图像，设置底色
     * 
     * @param void
     * @return void
     */
    private function createImage()
    {
        // 创建图像
        $this->image = imagecreatetruecolor($this->width, $this->height);
        
        // 创建背景色
        // $bg = imagecolorallocate($this->image, 63, 127, 206);
        $bg = imagecolorallocate($this->image, mt_rand(220, 255), mt_rand(220, 255), mt_rand(220, 255));
        
        // 填充背景色
        imagefilledrectangle($this->image, 0, 0, $this->width - 1, $this->height - 1, $bg);
    }

    /**
     * 设置干扰元素
     * 
     * @param void
     * @return void
     */
    private function setDisturb()
    {
        // 设置干扰点
        for ($i = 0; $i < 150; $i ++) {
            $color = imagecolorallocate($this->image, mt_rand(150, 200), mt_rand(150, 200), mt_rand(150, 200));
            imagesetpixel($this->image, mt_rand(5, $this->width - 10), mt_rand(5, $this->height - 3), $color);
        }
        
        // 设置干扰线
        for ($i = 0; $i < 10; $i ++) {
            $color = imagecolorallocate($this->image, mt_rand(150, 220), mt_rand(150, 220), mt_rand(150, 220));
            // $color = imagecolorallocate($this->image, 63, 127, 206);
            imagearc($this->image, mt_rand(- 10, $this->width), mt_rand(- 10, $this->height), mt_rand(30, 300), mt_rand(20, 200), 55, 44, $color);
        }
        
        // 创建边框色
        $border = imagecolorallocate($this->image, 63, 127, 206);
        
        // 画边框
        imagerectangle($this->image, 0, 0, $this->width - 1, $this->height - 1, $border);
    }

    /**
     * 产生并绘制验证码
     * 
     * @param void
     * @return void
     */
    private function setCaptcha()
    {
        $str = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
        
        // 生成验证码字符
        for ($i = 0; $i < $this->codeNum; $i ++) {
            $this->captcha .= $str{mt_rand(0, strlen($str) - 1)};
        }
        
        // 绘制验证码
        for ($i = 0; $i < strlen($this->captcha); $i ++) {
            // $color = imagecolorallocate($this->image, 255, 255, 255);
            $color = imagecolorallocate($this->image, mt_rand(0, 200), mt_rand(0, 200), mt_rand(0, 200));
            
            $x = floor(($this->width - 10) / $this->codeNum);
            $x = $x * $i + floor(($x - self::charWidth) / 2) + 5;
            $b = $this->height - 20;
            if (2 > $b) {
                $y = mt_rand($b, 2) * 1.1;
            } else {
                $y = mt_rand(2, $b) * 1.1;
            }
            imagechar($this->image, 5, $x, $y, $this->captcha{$i}, $color);
        }
    }

    /*
     * 输出图像
     * @param object $redis
     * @param string $account
     * @return void
     */
    private function exportImage($account)
    {
        header('Content-type:image/jpeg');
        imagejpeg($this->image);
    }
}  

